<template>
  <div>
    <div 
      id="modal" 
      ref="modal"
      :style="modalStyle"
    >
      <div id="modal-header" @mousedown="startDrag">
        <span>{{ title }}</span>
        <span id="modal-toggle" @click="togglePosition">⇄</span>
        <span id="modal-close" @click="closeModal">×</span>
      </div>
      <div 
        id="modal-content" 
        ref="modalContent"
      >
        <slot></slot>
      </div>
      <div 
        class="resize-handle" 
        @mousedown="startResize"
        v-if="!isRightAligned"
      ></div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'DraggableModal',
  props: {
    title: {
      type: String,
      default: '小宇'
    },
    isOpen: {
      type: Boolean,
      default: false
    },
    position: {
      type: Object,
      default: () => ({ 
        left: null,
        top: null,
        right: null,
        bottom: null
      })
    },
    // 初始化宽高
    size: {
      type: Object,
      default: () => ({ width: 640, height: 640 })
    },
    // 保持在中间
    keepCenter: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      isDragging: false,
      isResizing: false,
      dragOffset: { x: 0, y: 0 },
      bodyOverflow: '',
      localPosition: { 
        x: 0,
        y: 0,
        left: null,
        top: null,
        right: null,
        bottom: null
      },
      localSize: { ...this.size },
      isRightAligned: false,
      // 保存初始化尺寸
      initialSize: { ...this.size }
    }
  },
  computed: {
    modalStyle() {
      const style = {
        display: this.isOpen ? 'block' : 'none',
        width: `${this.localSize.width}px`,
        height: `${this.localSize.height}px`,
        cursor: this.isDragging ? 'grabbing' : 'default'
      };
      
      if (this.localPosition.left !== null) {
        style.left = `${this.localPosition.left}px`;
      }
      if (this.localPosition.top !== null) {
        style.top = `${this.localPosition.top}px`;
      }
      if (this.localPosition.right !== null) {
        style.right = `${this.localPosition.right}px`;
      }
      if (this.localPosition.bottom !== null) {
        style.bottom = `${this.localPosition.bottom}px`;
      }
      
      if (
        this.localPosition.left === null && 
        this.localPosition.right === null
      ) {
        style.left = `${this.localPosition.x}px`;
      }
      if (
        this.localPosition.top === null && 
        this.localPosition.bottom === null
      ) {
        style.top = `${this.localPosition.y}px`;
      }
      
      return style;
    }
  },
  watch: {
    isOpen(newVal) {
      if (newVal) {
        this.bodyOverflow = document.body.style.overflow;
        document.body.style.overflow = 'hidden';
        this.$nextTick(() => {
          if (this.keepCenter && !this.isRightAligned) {
            this.centerModal();
          }
        });
      } else {
        document.body.style.overflow = this.bodyOverflow;
      }
    },
    position: {
      deep: true,
      handler(newVal) {
        this.localPosition = { ...this.localPosition, ...newVal };
      }
    },
    size(newVal) {
      this.localSize = { ...newVal };
    }
  },
  mounted() {
    document.addEventListener('mousemove', this.handleMove);
    document.addEventListener('mouseup', this.handleUp);
    window.addEventListener('resize', this.handleWindowResize);
    this.localPosition = { 
      ...this.localPosition,
      ...this.position 
    };
    this.localSize = { ...this.size };
    // 保存初始化尺寸
    this.initialSize = { ...this.size };
  },
  beforeDestroy() {
    document.removeEventListener('mousemove', this.handleMove);
    document.removeEventListener('mouseup', this.handleUp);
    window.removeEventListener('resize', this.handleWindowResize);
    document.body.style.overflow = this.bodyOverflow;
  },
  methods: {
    closeModal() {
      this.$emit('close');
    },
    centerModal() {
      const bodyRect = document.body.getBoundingClientRect();
      // 恢复到初始化尺寸
      this.localSize = { ...this.initialSize };
      
      this.localPosition = {
        x: Math.max(0, (bodyRect.width - this.localSize.width) / 2),
        y: Math.max(0, (bodyRect.height - this.localSize.height) / 2),
        left: null,
        top: null,
        right: null,
        bottom: null
      };
      
      this.isRightAligned = false;
      this.$emit('update:position', { ...this.localPosition });
      this.$emit('update:size', { ...this.localSize });
    },
    alignRight() {
      const bodyRect = document.body.getBoundingClientRect();
      this.localPosition = {
        x: bodyRect.width - 480, // 通过x坐标实现右对齐
        y: Math.max(0, (bodyRect.height - bodyRect.height) / 2),
        left: null,
        top: null,
        right: null,
        bottom: null
      };
      this.localSize = {
        width: 480,
        height: bodyRect.height
      };
      this.isRightAligned = true;
      this.$emit('update:position', { ...this.localPosition });
      this.$emit('update:size', { ...this.localSize });
    },
    togglePosition() {
      if (this.isRightAligned) {
        // 切换到居中模式时，恢复初始化尺寸
        this.centerModal();
      } else {
        // 切换到居右模式
        this.alignRight();
      }
    },
    startDrag(e) {
      if (e.target.id === 'modal-close' || e.target.id === 'modal-toggle') return;
      
      this.isDragging = true;
      const rect = this.$refs.modal.getBoundingClientRect();
      this.dragOffset = {
        x: e.clientX - rect.left,
        y: e.clientY - rect.top
      };
      e.preventDefault();
    },
    startResize(e) {
      if (this.isRightAligned) return;
      
      this.isResizing = true;
      this.dragOffset = {
        x: e.clientX,
        y: e.clientY
      };
      e.preventDefault();
    },
    handleMove(e) {
      if (this.isDragging) {
        const bodyRect = document.body.getBoundingClientRect();
        let newX = e.clientX - this.dragOffset.x;
        let newY = e.clientY - this.dragOffset.y;

        if (this.isRightAligned) {
          newX = bodyRect.width - this.localSize.width;
        } else {
          newX = Math.max(0, Math.min(bodyRect.width - this.localSize.width, newX));
        }

        newY = Math.max(0, Math.min(bodyRect.height - this.localSize.height, newY));

        this.localPosition = {
          x: newX,
          y: newY,
          left: null,
          top: null,
          right: null,
          bottom: null
        };
        this.$emit('update:position', { ...this.localPosition });
      }
      
      if (this.isResizing && !this.isRightAligned) {
        const bodyRect = document.body.getBoundingClientRect();
        const minWidth = 300;
        const minHeight = 200;
        
        let newWidth = Math.max(minWidth, this.localSize.width + (e.clientX - this.dragOffset.x));
        let newHeight = Math.max(minHeight, this.localSize.height + (e.clientY - this.dragOffset.y));
        
        newWidth = Math.min(newWidth, bodyRect.width - this.localPosition.x);
        newHeight = Math.min(newHeight, bodyRect.height - this.localPosition.y);
        
        this.localSize = {
          width: newWidth,
          height: newHeight
        };
        
        this.dragOffset = {
          x: e.clientX,
          y: e.clientY
        };
        this.$emit('update:size', { ...this.localSize });
      }
    },
    handleUp() {
      if (this.isDragging || this.isResizing) {
        this.$emit('change', {
          position: { ...this.localPosition },
          size: { ...this.localSize },
          isOpen: this.isOpen
        });
      }
      this.isDragging = false;
      this.isResizing = false;
    },
    handleWindowResize() {
      if (this.isOpen) {
        if (this.isRightAligned) {
          this.alignRight();
        } else {
          const bodyRect = document.body.getBoundingClientRect();
          const modalRect = this.$refs.modal.getBoundingClientRect();
          
          if (modalRect.right > bodyRect.width || modalRect.bottom > bodyRect.height) {
            this.adjustModalPosition();
          }
        }
      }
    },
    adjustModalPosition() {
      const bodyRect = document.body.getBoundingClientRect();
      
      let newWidth = Math.min(this.localSize.width, bodyRect.width);
      let newHeight = Math.min(this.localSize.height, bodyRect.height);
      
      newWidth = Math.max(300, newWidth);
      newHeight = Math.max(200, newHeight);
      
      let newX = Math.min(this.localPosition.x, bodyRect.width - newWidth);
      let newY = Math.min(this.localPosition.y, bodyRect.height - newHeight);
      
      this.localPosition = { 
        x: newX, 
        y: newY,
        left: null,
        top: null,
        right: null,
        bottom: null
      };
      this.localSize = { width: newWidth, height: newHeight };
      
      this.$emit('update:position', { ...this.localPosition });
      this.$emit('update:size', { ...this.localSize });
    }
  }
}
</script>

<style scoped>
#modal {
  position: fixed;
  min-width: 300px;
  min-height: 200px;
  background-color: white;
  border-radius: 5px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  z-index: 9000;
}

#modal-header {
  position: absolute;
  width: 100%;
  top:0;
  left: 0;
  padding: 10px 15px;
  background-color: #3498db;
  box-sizing: border-box;
  color: white;
  cursor: move;
  user-select: none;
  flex-shrink: 0;
}

#modal-header:active {
  cursor: grabbing;
}

#modal-content {
  box-sizing: border-box;
  height: 100%;
  padding: 56px 20px 20px 20px;
  overflow:auto;
  flex-grow: 1;
  min-height: 0;
}

#modal-close {
  float: right;
  cursor: pointer;
  font-weight: bold;
  margin-left: 15px;
}

#modal-toggle {
  float: right;
  cursor: pointer;
  font-weight: bold;
}

.resize-handle {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 20px;
  height: 20px;
  background: linear-gradient(135deg, transparent 0%, transparent 50%, #3498db 50%, #3498db 100%);
  cursor: nwse-resize;
  z-index: 10;
}
</style>